package org.jgs1904.source;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * spring IOC  源码 学习
 *
 * @author 墨苍璃
 * @date 2023年08月21日23时11分
 */
public class Main {

    public static void main(String[] args) {

        /**
         * AnnotationConfigApplicationContext是Spring框架中的一个应用上下文容器，用于加载和管理基于注解的配置类，并实例化和管理应用程序中的bean。
         *
         * 它的主要作用包括：
         *
         * 1. 加载配置类：AnnotationConfigApplicationContext可以识别并加载使用@Configuration注解的配置类。配置类是Java类，通过对应用程序进行注解配置来定义bean和其依赖关系。
         *
         * 2. 实例化和管理bean：AnnotationConfigApplicationContext会根据配置类中的@Bean注解来实例化和管理bean。
         * 通过@Bean注解，可以将一个方法的返回值作为一个bean注册到容器中，并定义该bean的作用域、依赖关系等。
         *
         * 3. 自动扫描和注册组件：除了加载配置类外，AnnotationConfigApplicationContext还会自动扫描应用程序中的其他组件，如带有@Component注解的类，自动注册为bean。
         *
         * 4. 提供访问bean的能力：一旦所有的bean被实例化和管理后，AnnotationConfigApplicationContext提供了一种访问这些bean的能力。
         * 可以通过名称或类型来获取需要的bean实例，并在应用程序中使用它们。
         *
         * 5. 提供其他功能和扩展点：AnnotationConfigApplicationContext还提供了一些其他功能和扩展点，如事件发布与监听、AOP（面向切面编程）支持等。
         * 这些功能可以让开发人员更加方便地使用Spring框架。
         *
         * 总的来说，AnnotationConfigApplicationContext提供了一种基于注解的配置方式，使得开发人员可以通过注解来定义和管理应用程序中的bean，
         * 并提供了访问和使用这些bean的能力。它是Spring框架中一个非常重要的容器，用于实现依赖注入和控制反转等核心特性。
         */
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);

        /**
         * register(componentClasses)方法是Spring框架中的一个方法，用于将一组组件类（component classes）注册为Spring容器中的Bean。
         该方法的作用是将传入的componentClasses参数中的类解析为Bean定义，并将这些Bean定义注册到Spring容器中，以便后续可以在容器中对其进行管理和实例化。
         具体而言，register(componentClasses)方法的作用包括：
         1. 解析类：该方法会解析componentClasses参数中的每个类，根据注解或其他条件判断这些类是否应该被视为Spring的Bean。
         2. 创建Bean定义：对于被判断为Bean的类，register(componentClasses)方法会创建相应的Bean定义。这些Bean定义包含了Bean的名称、类型、作用域、依赖关系等信息。
         3. 注册Bean定义：一旦创建了Bean定义，register(componentClasses)方法会将这些定义注册到Spring容器的Bean工厂中。这样，后续可以根据这些定义在容器中实例化、管理和使用相应的Bean。
         4. 自动发现：该方法支持自动发现功能，当注册一个类时，它同样也会自动注册该类所依赖的其他Bean。这样可以避免手动配置所有的依赖关系。
         总的来说，register(componentClasses)方法的主要作用是将一组组件类注册为Spring容器中的Bean。它通过解析类、创建Bean定义以及注册定义的方式，
         实现了自动化地添加组件到Spring容器的功能。这种方式减少了手动配置的工作量，使得组件的管理更加便利和灵活。
         *
         *
         *
         * refresh()方法是Spring框架中ApplicationContext接口提供的一个方法，用于启动Spring容器并进行刷新操作。         *
         * refresh()方法的作用包括：
         * 1. 初始化容器：在调用refresh()方法之前，应用程序上下文（ApplicationContext）已经被创建，
         * 但还未完成初始化。调用refresh()方法会触发容器的初始化过程，包括加载配置、解析Bean定义、创建Bean实例等。
         * 2. 刷新容器：refresh()方法会执行容器的刷新操作，即重新加载或重新初始化容器中的所有Bean。
         * 它会触发一系列的生命周期回调和事件处理，确保容器中的所有Bean都处于正确的状态。
         * 3. 加载Bean：refresh()方法会根据配置或注解解析Bean定义，并实例化这些Bean。
         * 它会扫描配置文件、扫描类路径、扫描注解等方式来加载Bean，并在需要时解决Bean之间的依赖关系。
         * 4. 处理Bean生命周期：refresh()方法会调用BeanFactoryPostProcessor和BeanPostProcessor接口实现类的相应方法，
         * 对Bean进行后置处理。这些处理包括对Bean定义的修改、Bean属性的设置、Bean初始化前后的操作等。
         * 5. 发布容器事件：refresh()方法会触发和发布容器相关的事件，例如容器的初始化完成事件、Bean创建事件、属性设置事件等。
         * 这些事件可以被外部监听器捕获并进行相应的处理。
         * 总的来说，refresh()方法的主要作用是启动Spring容器并进行刷新操作，包括加载Bean定义、创建Bean实例、处理Bean生命周期以及发布容器事件等。
         * 它确保容器中的所有Bean都被正确地加载和初始化，并使容器处于可用状态，可以提供服务。
         */
//        public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
//            this();
//            register(componentClasses);
//            refresh();
//        }

        /**
         * AnnotationConfigApplicationContext 父类  GenericApplicationContext 构造函数
         *
         * DefaultListableBeanFactory是Spring框架中的一个bean工厂的实现类，用于加载、实例化、管理和解析bean对象的工厂。
         *
         * 它的主要作用包括：
         *
         * 1. 加载bean定义：DefaultListableBeanFactory可以从不同的资源（如XML配置文件、注解配置类等）中加载bean的定义。它会解析这些资源，提取和注册bean定义信息。
         *
         * 2. 实例化和管理bean：DefaultListableBeanFactory负责实例化和管理应用程序中的所有bean对象。
         * 它会根据bean定义信息，通过反射创建bean的实例，并根据需要进行初始化、属性注入等操作。
         *
         * 3. 提供bean的依赖注入：DefaultListableBeanFactory支持依赖注入，即自动将依赖的对象注入到相应的bean中。
         * 它会根据bean定义信息，自动解析依赖关系，实现依赖的自动注入。
         *
         * 4. 提供bean的作用域管理：DefaultListableBeanFactory可以管理bean的作用域，
         * 包括单例、原型等作用域。它会根据bean定义的作用域配置，决定如何创建和管理bean的实例，提供相应的作用域管理功能。
         *
         * 5. 提供AOP（面向切面编程）支持：DefaultListableBeanFactory支持AOP功能，
         * 可以通过配置切点、通知等，实现对目标对象的动态代理和增强。它可以将切面逻辑和业务逻辑解耦，提供更强大的扩展能力。
         *
         * 6. 提供bean的后置处理器支持：DefaultListableBeanFactory支持自定义的BeanPostProcessor接口，
         * 在bean实例化前后进行一些处理。这些处理包括初始化前的处理、初始化后的处理等，可以在处理过程中对bean对象进行操作和扩展。
         *
         * 7. 提供对bean的持久化和多次加载的支持：DefaultListableBeanFactory支持对bean的持久化和多次加载。
         * 它可以将bean的定义信息持久化到外部存储（如数据库、文件等），并可以根据需要多次加载这些定义信息，实现动态的bean管理和配置。
         *
         * 总的来说，DefaultListableBeanFactory是Spring框架中一个核心且重要的组件，用于加载、实例化、管理和解析bean对象。
         * 它提供了丰富的功能和扩展点，能够满足不同应用场景下的需求。通过DefaultListableBeanFactory，开发人员可以灵活、高效地管理和使用Spring容器中的bean对象。
         *
         */
        //  public GenericApplicationContext() {
        //    this.beanFactory = new DefaultListableBeanFactory();
        //  }


        /**AnnotationConfigApplicationContext 自己的构造函数
         *AnnotatedBeanDefinitionReader是Spring框架中的一个类，用于读取和解析带有注解的Java类，将其转化为相应的Bean定义，在Spring容器中进行管理和实例化。
         * 它的主要作用包括：
         * 1. 解析注解：AnnotatedBeanDefinitionReader会扫描指定的Java类，解析其中的注解信息。它支持处理多个常用的Spring注解，比如@Component、@Service、@Controller等，以及自定义的注解。
         * 2. 创建Bean定义：在解析注解的过程中，AnnotatedBeanDefinitionReader会根据注解的信息创建对应的Bean定义。它会解析注解中的属性值，确定Bean的名称、类型、作用域、依赖关系等。
         * 3. 注册Bean定义：AnnotatedBeanDefinitionReader将解析得到的Bean定义注册到Spring容器的Bean工厂中，供容器后续使用。这样，可以在容器中通过名称或类型获取并实例化相应的Bean。
         * 4. 支持的注解：AnnotatedBeanDefinitionReader支持多个常用的注解，并提供了相应的处理逻辑。
         * 这些注解包括@Component、@Configuration、@Service、@Repository等，它们可以用于标识不同类型的Bean并指定其特定的属性和行为。
         * 5. 注解配置方式：AnnotatedBeanDefinitionReader为使用注解进行配置的Spring应用提供了便利。相比传统的XML配置，
         * 注解配置更加简洁和灵活，可以在Java类中直接使用注解来定义Bean和配置相关属性。
         * 总的来说，AnnotatedBeanDefinitionReader的主要作用是读取和解析带有注解的Java类，
         * 将其转化为Spring容器中的Bean定义，实现对注解配置的管理和使用。通过AnnotatedBeanDefinitionReader，开发人员可以更加方便和灵活地使用注解来定义和配置Spring的Bean。
         *
         *
         *
         * ClassPathBeanDefinitionScanner是Spring框架中的一个类，用于扫描类路径（Classpath）上的特定包或包含特定注解的类，将它们解析为Bean定义并注册到Spring容器中。
         * ClassPathBeanDefinitionScanner的主要作用如下：
         * 1. 扫描类路径：ClassPathBeanDefinitionScanner会根据指定的包名或类路径，递归地扫描符合条件的类。它支持通配符和正则表达式，可以进行更加灵活的匹配。
         * 2. 解析类和注解：在扫描过程中，ClassPathBeanDefinitionScanner会解析每个扫描到的类。它可以检查类上的注解，以确定哪些类应该被视为Spring的Bean。
         * 3. 创建Bean定义：一旦确定某个类符合Bean定义的条件（例如标注了特定的注解），ClassPathBeanDefinitionScanner将会创建对应的Bean定义。
         * 这些Bean定义包括Bean的名称、类型、作用域、依赖关系等信息。
         * 4. 注册Bean定义：ClassPathBeanDefinitionScanner会将解析得到的Bean定义注册到Spring容器的Bean工厂中。
         * 这样，后续在容器中就可以根据这些定义实例化和管理相应的Bean。
         * 5. 支持的扫描条件：ClassPathBeanDefinitionScanner可以根据不同的需求配置不同的扫描条件。
         * 它支持扫描特定的包名、扫描特定的注解、扫描特定的类等，可以根据需要进行定制。
         * 总的来说，ClassPathBeanDefinitionScanner的主要作用是扫描类路径上特定包或包含特定注解的类，
         * 并将其解析为Spring容器中的Bean定义。它为Spring的自动化配置提供了便利，可以根据配置的扫描条件自动发现并注册合适的Bean定义，减少手动配置的繁琐。
         */
//        public AnnotationConfigApplicationContext() {
//            StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
//            this.reader = new AnnotatedBeanDefinitionReader(this);
//            createAnnotatedBeanDefReader.end();
//            this.scanner = new ClassPathBeanDefinitionScanner(this);
//        }


/**invokeBeanFactoryPostProcessors(beanFactory)方法是Spring框架中的一个方法，用于执行注册到容器中的BeanFactoryPostProcessor实例的后置处理方法。
 该方法的作用包括：
 1. 获取BeanFactoryPostProcessor的实例：首先，invokeBeanFactoryPostProcessors(beanFactory)方法通过beanFactory参数获取容器中已注册的所有BeanFactoryPostProcessor的实例。
 这些实例是在容器启动过程中通过注册机制添加到容器中的。
 2. 执行BeanFactoryPostProcessor的后置处理方法：接下来，对于每个获取到的BeanFactoryPostProcessor实例，
 invokeBeanFactoryPostProcessors(beanFactory)方法会依次调用其实现的postProcessBeanFactory()方法。
 这个方法允许BeanFactoryPostProcessor对容器的BeanFactory进行自定义的修改或扩展。
 3. 执行顺序：在调用postProcessBeanFactory()方法时，方法执行的顺序是根据BeanFactoryPostProcessor实例的优先级
 （实现了PriorityOrdered接口的在前，实现了Ordered接口的在后）和注册的顺序来确定的。高优先级的BeanFactoryPostProcessor会先于低优先级的执行。
 4. BeanFactory的修改或扩展：在执行postProcessBeanFactory()方法期间，
 BeanFactoryPostProcessor可以通过访问和修改BeanFactory的属性和配置，例如添加BeanDefinition、修改BeanDefinition的属性、注册BeanPostProcessor等。
 总而言之，invokeBeanFactoryPostProcessors(beanFactory)方法的作用是执行容器中所有注册的BeanFactoryPostProcessor实例的后置处理方法。
 通过执行这些方法，BeanFactoryPostProcessor可以对容器的BeanFactory进行自定义的修改或扩展，以满足特定的需求。
 这个方法通常在容器初始化的早期阶段被调用，确保在容器实例化Bean之前，BeanFactoryPostProcessor的处理逻辑被执行。
 *
 *
 * registerBeanPostProcessors(beanFactory)方法是Spring框架中的一个方法，用于注册BeanPostProcessor的实例到容器的Bean工厂中。
 * 该方法的作用包括：
 * 1. 获取BeanPostProcessor的实例：首先，registerBeanPostProcessors(beanFactory)方法会获取容器中已注册的所有BeanPostProcessor的实例。
 * 这些实例是在容器启动过程中通过注册机制添加到容器中的。
 * 2. 注册BeanPostProcessor实例：接下来，对于每个获取到的BeanPostProcessor实例，
 * registerBeanPostProcessors(beanFactory)方法会将其注册到容器的Bean工厂中，以便在容器中对其进行管理和使用。
 * 3. BeanPostProcessor的作用：通过注册BeanPostProcessor实例，可以在Bean的实例化和初始化过程中插入自定义逻辑。
 * BeanPostProcessor接口提供了两个方法：postProcessBeforeInitialization()和postProcessAfterInitialization()，
 * 可以在Bean初始化前后进行自定义的处理，例如修改Bean属性、添加AOP代理等。
 * 4. 执行顺序：在容器中注册BeanPostProcessor实例时，注重执行的顺序。通过Spring框架提供的Order注解和PriorityOrdered接口，
 * 可以控制BeanPostProcessor的执行顺序，确保在初始化Bean时按照特定的顺序应用后处理逻辑。
 * 总的来说，registerBeanPostProcessors(beanFactory)方法的主要作用是将容器中已注册的BeanPostProcessor实例注册到容器的Bean工厂中，
 * 以便在Bean的实例化和初始化过程中提供自定义的处理逻辑。这些处理逻辑可以在Bean初始化之前和之后执行，并由注册的顺序和优先级控制。
 * 通过BeanPostProcessor，可以对Bean进行更高级的定制和增强，实现对Bean的AOP、代理、注解处理等功能。
 *
 *
 * finishBeanFactoryInitialization(beanFactory)方法是Spring框架中的一个方法，用于完成Bean工厂的初始化过程，包括实例化、属性填充和初始化。
 * 该方法的作用包括：
 * 1. 实例化Bean：首先，finishBeanFactoryInitialization(beanFactory)方法会遍历容器中所有的Bean定义，
 * 并根据定义信息创建Bean的实例。在创建实例时，会根据定义的作用域（Singleton、Prototype等）决定是否需要创建多个实例。
 * 2. 属性填充：对于每个被实例化的Bean，finishBeanFactoryInitialization(beanFactory)方法会根据Bean定义中的属性信息，
 * 将相应的属性值填充到Bean实例中。属性填充是通过反射机制实现的，可以根据定义的属性名称和类型，在Bean实例中进行相应的字段赋值。
 * 3. 初始化Bean：在实例化和属性填充完成后，finishBeanFactoryInitialization(beanFactory)方法会调用Bean的初始化方法。
 * 初始化方法可以通过实现InitializingBean接口的afterPropertiesSet()方法或通过配置文件中的init-method指定。
 * 4. 依赖注入：在初始化Bean的过程中，如果存在依赖关系（通过@Autowired注解或XML配置定义），
 * finishBeanFactoryInitialization(beanFactory)方法会自动解析并注入依赖的Bean。
 * 5. 后置处理：在完成Bean的初始化之后，finishBeanFactoryInitialization(beanFactory)
 * 方法会调用实现了BeanPostProcessor接口的实现类的postProcessAfterInitialization()方法，对Bean进行一些自定义后置处理。
 * 总的来说，finishBeanFactoryInitialization(beanFactory)方法的作用是完成Bean工厂的初始化过程。它会遍历所有的Bean定义，
 * 创建实例、填充属性、初始化Bean，并进行依赖注入和后置处理。通过这个方法，Spring容器能够确保所有的Bean都被正确地创建、初始化和配置，并且满足依赖关系，可以在应用程序中使用。
 */
//        public void refresh() throws BeansException, IllegalStateException {
//            synchronized (this.startupShutdownMonitor) {
//                StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
//
//                // Prepare this context for refreshing.
//                prepareRefresh();
//
//                // Tell the subclass to refresh the internal bean factory.
//                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//
//                // Prepare the bean factory for use in this context.
//                prepareBeanFactory(beanFactory);
//
//                try {
//                    // Allows post-processing of the bean factory in context subclasses.
//                    postProcessBeanFactory(beanFactory);
//
//                    StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
//                    // Invoke factory processors registered as beans in the context.
//                    invokeBeanFactoryPostProcessors(beanFactory);
//
//                    // Register bean processors that intercept bean creation.
//                    registerBeanPostProcessors(beanFactory);
//                    beanPostProcess.end();
//
//                    // Initialize message source for this context.
//                    initMessageSource();
//
//                    // Initialize event multicaster for this context.
//                    initApplicationEventMulticaster();
//
//                    // Initialize other special beans in specific context subclasses.
//                    onRefresh();
//
//                    // Check for listener beans and register them.
//                    registerListeners();
//
//                    // Instantiate all remaining (non-lazy-init) singletons.
//                    finishBeanFactoryInitialization(beanFactory);
//
//                    // Last step: publish corresponding event.
//                    finishRefresh();
//                }
//
//                catch (BeansException ex) {
//                    if (logger.isWarnEnabled()) {
//                        logger.warn("Exception encountered during context initialization - " +
//                                "cancelling refresh attempt: " + ex);
//                    }
//
//                    // Destroy already created singletons to avoid dangling resources.
//                    destroyBeans();
//
//                    // Reset 'active' flag.
//                    cancelRefresh(ex);
//
//                    // Propagate exception to caller.
//                    throw ex;
//                }
//
//                finally {
//                    // Reset common introspection caches in Spring's core, since we
//                    // might not ever need metadata for singleton beans anymore...
//                    resetCommonCaches();
//                    contextRefresh.end();
//                }
//            }
//        }

    }

}
